package com.tengju.data.application.user;

import com.tengju.data.domain.model.cdc.CDCEvent;
import com.tengju.data.domain.model.cdc.CdcUserRepository;
import com.tengju.data.domain.model.cdc.TableUserBrandProvider;
import com.tengju.data.domain.model.service.CDCEventHandleService;
import com.tengju.data.domain.model.user.UserLevelEnum;
import com.tengju.data.domain.shared.CastUtil;
import com.tengju.user.domain.shared.DateUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.List;
import java.util.Map;

import static com.tengju.user.domain.shared.DateUtil.DATE_TIME_FORMAT;


@Service
@Slf4j
public class UserInfoCDCEventHandleService implements CDCEventHandleService<CDCEvent> {

    @Autowired
    CdcUserRepository userRepository;

    private String TABLE_NAME = "w_user_brand_provider";

    @Override
    public boolean hitEvent(CDCEvent cdcEvent) {
        return StringUtils.isNotBlank(cdcEvent.getTable()) && TABLE_NAME.equals(cdcEvent.getTable());
    }

    @Override
    @Transactional(value = "dataTransactionManager",rollbackFor = Exception.class)
    public void processInsert(CDCEvent cdcEvent) {
        List<Map<String, String>> curDataList = cdcEvent.getData();
        for (Map<String, String> curData : curDataList) {
            long idCode = CastUtil.castLong(curData.get(TableUserBrandProvider.id_code.name()));
            int level = CastUtil.castInt(curData.get(TableUserBrandProvider.brand_provider_level.name()));
            if (level != UserLevelEnum.BLACK.getCode()) {
//                log.info("新增用户不是黑卡，不处理，idCode:{},level:{}",idCode,level);
                continue;
            }
            long pIdCode = CastUtil.castLong(curData.get(TableUserBrandProvider.p_id_code.name()));
            String createTime = curData.get(TableUserBrandProvider.created_at.name());
            if (StringUtils.isBlank(createTime)) {
                createTime = DateUtil.formartLocalDateTime(DATE_TIME_FORMAT,getEventTime(cdcEvent));
            }
            String sourceUpdateTime = DateUtil.formartLocalDateTime(DATE_TIME_FORMAT,getEventTime(cdcEvent));
            userRepository.saveOrUpdateByCdc(idCode,pIdCode,level,createTime,sourceUpdateTime);
        }
    }

    @Override
    @Transactional(value = "dataTransactionManager",rollbackFor = Exception.class)
    public void processUpdate(CDCEvent cdcEvent) {
        List<Map<String, String>> oldDataList = cdcEvent.getOld();
        List<Map<String, String>> curDataList = cdcEvent.getData();
        for (int i = 0; i < oldDataList.size(); i++) {
            Map<String, String> oldData = oldDataList.get(i);
            Map<String, String> curData = curDataList.get(i);
            long idCode = CastUtil.castLong(curData.get(TableUserBrandProvider.id_code.name()));
            int afterLevel = CastUtil.castInt(curData.get(TableUserBrandProvider.brand_provider_level.name()));
            int beforeLevel = afterLevel;
            String levelChangeTime = null;
            if (oldData.containsKey(TableUserBrandProvider.brand_provider_level.name())) {
                beforeLevel = CastUtil.castInt(oldData.get(TableUserBrandProvider.brand_provider_level.name()));
                levelChangeTime = curData.get(TableUserBrandProvider.updated_at.name());
            }
            if (afterLevel != UserLevelEnum.BLACK.getCode() &&  beforeLevel != UserLevelEnum.BLACK.getCode()) {
//                log.info("不是黑卡数据变更，不处理，idCode:{},beforeLevel:{},afterLevel:{}",idCode,beforeLevel,afterLevel);
                continue;
            }
            if (!oldData.containsKey(TableUserBrandProvider.p_id_code.name()) && !oldData.containsKey(TableUserBrandProvider.brand_provider_level.name())) {
//                log.info("不是上级变更或者等级变更，不处理，idCode:{},oldData:{}",idCode,oldData);
                continue;
            }
            log.info("黑卡等级相关变更,event:{}",cdcEvent);
            long pIdCode = CastUtil.castLong(curData.get(TableUserBrandProvider.p_id_code.name()));
            String sourceUpdateTime = DateUtil.formartLocalDateTime(DATE_TIME_FORMAT,getEventTime(cdcEvent));
            userRepository.saveOrUpdateByCdc(idCode,pIdCode,afterLevel,levelChangeTime,sourceUpdateTime);
        }
    }

    @Override
    @Transactional(value = "dataTransactionManager",rollbackFor = Exception.class)
    public void processDelete(CDCEvent cdcEvent) {
        List<Map<String, String>> curDataList = cdcEvent.getData();
        for (Map<String, String> curData : curDataList) {
            long idCode = CastUtil.castLong(curData.get(TableUserBrandProvider.id_code.name()));
            log.info("用户数据删除,idCode:{}",idCode);
            userRepository.deleteByIdCode(idCode);
        }
    }

    private LocalDateTime getEventTime(CDCEvent cdcEvent) {
        Long eventTs = cdcEvent.getEventTs();
        return LocalDateTime.ofInstant(Instant.ofEpochMilli(eventTs), ZoneId.systemDefault());
    }

}
